//
//  QSScanQRCodeViewController.m
//  ToyTraceabilitySystem
//
//  Created by apple on 2017/6/26.
//  Copyright © 2017年 Song. All rights reserved.
//

#import "QSScanQRCodeViewController.h"

#import <AVFoundation/AVFoundation.h>

#import "QSScanQRCodeView.h"

#define kScanSoundName @"sound.caf"

@interface QSScanQRCodeViewController ()<AVCaptureMetadataOutputObjectsDelegate>
/** 会话对象 */
@property (nonatomic, strong) AVCaptureSession *session;
/** 图层类 */
@property (nonatomic, strong) AVCaptureVideoPreviewLayer *previewLayer;
/** 扫描的框框界面 */
@property (nonatomic, strong) QSScanQRCodeView *scanView;
@end

@implementation QSScanQRCodeViewController
#pragma mark - 生命周期
- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    
    // 穿透导航栏
    self.edgesForExtendedLayout = UIRectEdgeNone;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    
    // 设置二维码扫描
    [self setupScanQRCode];
    
    self.view.backgroundColor = [UIColor blackColor];
    UIImageView *imageViewBar = self.navigationController.navigationBar.subviews.firstObject;
    imageViewBar.alpha = 1.0;
    
    // 创建扫描边框
    self.scanView = [[QSScanQRCodeView alloc] initWithFrame:self.view.frame outsideViewLayer:self.view.layer];
    [self.view addSubview:self.scanView];
}

- (void)viewDidDisappear:(BOOL)animated {
    [super viewDidDisappear:animated];
    
    /** 移除定时器 */
    [self.scanView removeTimer];
    [self.scanView removeFromSuperview];
    self.scanView = nil;
}

/**
 *  设置二维码扫描
 */
- (void)setupScanQRCode
{
    // 获取摄像设备
    AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    
    if (device) {
        // 判断授权状态
        AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
        if (authStatus == AVAuthorizationStatusRestricted) {
            NSLog(@"因为系统原因, 无法访问相机");
            return;
        } else if (authStatus == AVAuthorizationStatusDenied) { // 用户拒绝当前应用访问相机
            UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"警告" message:@"请去-> [设置 - 隐私 - 相机 - 摩宝网] 打开访问开关" delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"去设置", nil];
            [alertView show];
            return;
        } else if (authStatus == AVAuthorizationStatusAuthorized) { // 用户允许当前应用访问相机
            [self allowScan];
        } else if (authStatus == AVAuthorizationStatusNotDetermined) { // 用户还没有做出选择
            QSWeakSelf;
            // 弹框请求用户授权
            [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
                dispatch_async(dispatch_get_main_queue(), ^{
                    if (granted) {
                        // 用户接受
                        [weakSelf allowScan];
                    } else {
                        [weakSelf.navigationController popViewControllerAnimated:YES];
                    }
                });
            }];
        }
    } else {
        UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"警告" message:@"未检测到您的摄像头, 请在真机上测试" delegate:self cancelButtonTitle:@"好的" otherButtonTitles:nil, nil];
        [alertView show];
        return;
    }
}

/**
 *  允许扫描
 */
- (void)allowScan
{
    AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    // 创建输入流
    AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device error:nil];
    
    // 创建输出流
    AVCaptureMetadataOutput *output = [[AVCaptureMetadataOutput alloc] init];
    
    // 设置代理 在主线程里刷新
    [output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
    
    // 设置扫描范围(每一个取值0～1，以屏幕右上角为坐标原点)
    output.rectOfInterest = CGRectMake(0.05, 0.2, 0.7, 0.6);
    
    // 初始化链接对象（会话对象）
    self.session = [[AVCaptureSession alloc] init];
    // 高质量采集率
    [_session setSessionPreset:AVCaptureSessionPresetHigh];
    
    // 添加会话输入
    [_session addInput:input];
    
    // 添加会话输出
    [_session addOutput:output];
    
    // 设置输出数据类型，需要将元数据输出添加到会话后，才能指定元数据类型，否则会报错
    // 设置扫码支持的编码格式(如下设置条形码和二维码兼容)
    output.metadataObjectTypes = @[AVMetadataObjectTypeQRCode, AVMetadataObjectTypeEAN13Code,  AVMetadataObjectTypeEAN8Code, AVMetadataObjectTypeCode128Code];
    
    // 实例化预览图层, 传递_session是为了告诉图层将来显示什么内容
    self.previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:_session];
    _previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
    _previewLayer.frame = self.view.layer.bounds;
    
    // 将图层插入当前视图
    [self.view.layer insertSublayer:_previewLayer atIndex:0];
    
    [self performSelector:@selector(startSessionRun) withObject:nil afterDelay:0.0f inModes:@[NSRunLoopCommonModes]];
}

/**
 *  启动会话
 */
- (void)startSessionRun
{
    [_session startRunning];
}

/**
 *  设置扫描完成后的提示音
 */
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection {
    // 扫描成功之后的提示音
    [self playSoundEffect:kScanSoundName];
    
    // 如果扫描完成，停止会话
    [self.session stopRunning];
    
    // 删除预览图层
    [self.previewLayer removeFromSuperlayer];
    
    // 设置界面显示扫描结果
    if (metadataObjects.count > 0) {
        AVMetadataMachineReadableCodeObject *obj = metadataObjects[0];
        
        if ([obj.stringValue hasPrefix:@"http"] || [obj.stringValue hasPrefix:@"https"]) {
            if ([self.delegate respondsToSelector:@selector(scanSuccessWithUrl:)]) {
                [self.delegate scanSuccessWithUrl:obj.stringValue];
            }
            [self.navigationController popViewControllerAnimated:YES];
        } else { // 扫描结果为条形码
            if ([self.delegate respondsToSelector:@selector(scanSuccessWithUrl:)]) {
                [self.delegate scanSuccessWithUrl:obj.stringValue];
            }
            [self.navigationController popViewControllerAnimated:YES];
        }
    }
}

#pragma mark - - - 扫描提示声
/**
 *  播放完成回调函数(这是一个C语言函数)
 *
 *  @param soundID    系统声音ID
 *  @param clientData 回调时传递的数据
 */
void soundCompleteCallback(SystemSoundID soundID,void * clientData){
    QSLog(@"播放完成...");
}

/**
 *  播放音效文件
 *
 *  @param name 音频文件名称
 */
- (void)playSoundEffect:(NSString *)name{
    NSString *audioFile = [[NSBundle mainBundle] pathForResource:name ofType:nil];
    NSURL *fileUrl = [NSURL fileURLWithPath:audioFile];
    // 获得系统声音ID
    SystemSoundID soundID = 0;
    /**
     * in FileUrl:音频文件url
     * out SystemSoundID:声音id（此函数会将音效文件加入到系统音频服务中并返回一个长整形ID）
     */
    AudioServicesCreateSystemSoundID((__bridge CFURLRef)(fileUrl), &soundID);
    
    // 如果需要在播放完之后执行某些操作，可以调用如下方法注册一个播放完成回调函数
    AudioServicesAddSystemSoundCompletion(soundID, NULL, NULL, soundCompleteCallback, NULL);
    
    // 播放音频
    AudioServicesPlaySystemSound(soundID); // 播放音效
}

#pragma mark - UIAlertViewDelegate
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
    if (buttonIndex == 1) {
        // 系统是否大于10
        NSURL *url = nil;
        if ([[UIDevice currentDevice] systemVersion].floatValue < 10.0) {
            url = [NSURL URLWithString:@"prefs:root=privacy"];
            
        } else {
            url = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
        }
        [[UIApplication sharedApplication] openURL:url];
    }
}
@end
